#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include <sys/types.h>//open
#include <sys/stat.h>//open
#include <fcntl.h>//open
#include <unistd.h>//close
#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <linux/input.h>

//////////////////////// TCP结构体
typedef struct {
    char username[1024];
    char password[1024];
} User;

User users[100]; // 存储最多100个用户
int numUsers = 0; // 当前的用户数量
////////////////////////

//////////////////////// 增删查改
typedef float SLTDataType;

typedef struct SListNode
{
	SLTDataType tem;
	SLTDataType hum;
	long long data;
	struct SListNode* next;
}SLTNode;

SLTNode* BuySListNode(SLTDataType x, SLTDataType y, long long z)//申请新的节点
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->tem = x;
	newnode->hum = y;
	newnode->data = z;
	newnode->next = NULL;
}

void SLTPrint(SLTNode* phead)//打印全部节点
{
	SLTNode* cur = phead;
	while (cur)
	{
		printf("当前日期：%lld 当前温度：%.2f℃  当前湿度：%.2f ", cur->data, cur->tem, cur->hum);
		cur = cur->next;
		printf("\n");
	}

}


void SLTPushBack(SLTNode** pphead, SLTDataType x, SLTDataType y, long long z)//尾插
{
	SLTNode* newnode = BuySListNode(x, y, z);
	//pphead空指针，对地址进行操作
	if (!*pphead)
		*pphead = newnode;
	else//不为空，以下为对结构体进行操作
	{

		SLTNode* dit = *pphead;
		while (dit->next)
		{
			dit = dit->next;
		}
		dit->next = newnode;
	}
}

void input(SLTNode** pphead)
{
	printf("请输入要录入的数据：\n");
	printf("日期(格式：20231212)：");
	long long da = 0;
	scanf("%lld", &da);
	printf("温度:");
	float tm = 0;
	scanf("%f", &tm);
	printf("湿度:");
	float hu = 0;
	scanf("%f", &hu);
	SLTPushBack(pphead, tm, hu, da);

}

void SLTPopBack(SLTNode** pphead, SLTNode* pos)//尾删
{
	assert(pphead);

	SLTNode* cur = *pphead;
	SLTNode* prev = *pphead;
	while (cur != pos)
	{
		prev = cur;
		SLTNode* next = cur->next;
		cur = next;
	}
	if (cur == *pphead)
	{
		*pphead = cur->next;
		free(cur);
	}
	else
	{
		prev->next = cur->next;
		free(cur);
	}

}


SLTNode* SLTFind(SLTNode* phead, long long x)//查找
{
	//判空
	assert(phead);
	//遍历找值
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

void Change(SLTNode* phead, long long x)
{
	SLTNode* cur = SLTFind(phead, x);
	if (cur)
	{
		SLTDataType tm;
		SLTDataType hu;
		printf("输入要修改的温度：");
		scanf("%f", &tm);
		printf("输入要修改的湿度：");
		scanf("%f", &hu);
		cur->hum = hu;
		cur->tem = tm;

	}
}


void SLTDestroy(SLTNode** pphead)
{
	assert(pphead);

	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);

		cur = next;
	}

	*pphead = NULL;
}
////////////////////////

////////////////////////文件操作
void Savefile(SLTNode* pphead)
{
	FILE* fp=fopen("1.txt","w+");
	if (fp == NULL) {
        printf("无法打开文件。\n");
    	exit(-1);
	}
	//fseek(fp, 0, SEEK_SET);
	SLTNode* cur=pphead;
	while(cur)
	{	
		fprintf(fp, "%lld %f %f\n", cur->data,cur->tem,cur->hum);
		cur=cur->next;
	}

	fclose(fp);
}

void Readfile(SLTNode** pphead)
{
	FILE* pf = fopen("1.txt", "r");
	long long da=0;
	float tm=0;
	float hu=0;
	if (pf != NULL)
	{
		while (fscanf(pf, "%lld %f %f", &da, &tm, &hu) != EOF) {
        // 在这里处理日期和时间
		SLTPushBack(pphead, tm, hu, da);
    }
	}
	fclose(pf);
}


///////////////////////菜单

void menu()
{
	printf(" ———————————————————————————————\n");
	printf(" ———————智慧农业管理系统————————\n");
	printf(" ———1.插入数据     2.修改数据———\n ");
	printf("———3.显示数据     4.删除数据———\n ");
	printf("———5.删除所有数据  6.退出系统———\n");
	printf(" ———————————————————————————————\n");
}

void excute(int socket_fd);
///////////////////////////////////////////////////////////////////--TCP 登录注册函数

void register_user(const char* username, const char* password) {
    strncpy(users[numUsers].username, username, sizeof(users[numUsers].username) - 1);
    strncpy(users[numUsers].password, password, sizeof(users[numUsers].password) - 1);
    printf("Registered user: %s, password: %s\n", users[numUsers].username, users[numUsers].password);
    numUsers++;
}

int check_login(const char* username, const char* password) {
    for(int i = 0; i < numUsers; i++) {
        if(strcmp(users[i].username, username) == 0 && strcmp(users[i].password, password) == 0) {
            return 1; // 登录成功
        }
    }
    return 0; // 登录失败
}

void* handle_client(void* arg) {
    int conn_fd = *(int*)arg;
    FILE* file = NULL;
    int is_logged_in = 0; // 添加一个标志来表示用户是否已经登录成功

    while(1) {
        char data[200];
        ssize_t numBytesRcvd;
        ssize_t numBytesRcvd1;
        if((numBytesRcvd = recv(conn_fd, data, sizeof(data) - 1, 0)) > 0) {
            data[numBytesRcvd] = '\0';
            printf("Received data: %s\n", data);

            char type[10];
            char username[1024];
            char password[1024];
            if (sscanf(data, "%[^:]: %s password: %s", type, username, password) == 3) {
                if (strncmp(type, "register", 8) == 0) {
                    register_user(username, password);
                    printf("Registered new user: %s\n", username);
                } else if (strncmp(type, "login", 5) == 0) {
                    if(check_login(username, password)) {
                        printf("Login successful\n");
                        file = fopen("1.txt", "w");
                        printf("打开1.txt成功\n");// 打开文件，准备写入数据
                        is_logged_in = 1; 
                        printf("登录标志设置成功\n");// 设置登录成功标志
                    } else {
                        printf("Login failed\n");
						exit(-2);
                        //break; // 登录失败，结束线程
                    }
                }
            } 
            
            if (is_logged_in && file != NULL) { // 登录成功，开始接收数据
                char success_msg[] = "Login successful";
                send(conn_fd, success_msg, sizeof(success_msg), 0); 
                printf("发送登陆成功\n");// 发送登录成功的确认消息
                long long msg[3];
                printf("准备接收数据\n");
                while(1){
                memset(msg, 0, sizeof(msg)); // 初始化数组，数组中的值全部赋值为0

                numBytesRcvd1 = recv(conn_fd, msg, sizeof(msg), 0);
                if(numBytesRcvd1 < 0) {
                    perror("recv failed");
                    break;
                } else if(numBytesRcvd1 == 0) {
                    printf("Client disconnected\n");
                    break;
                }
                if(msg[0]==1&&msg[1]==2&&msg[2]==3) {
					printf("进入系统 \n");
                    excute(conn_fd);
                }else{
					printf("Received: %lld %f %f\n", msg[0],(float)msg[1],(float)msg[2]);
                    fprintf(file, "%lld %f %f\n", msg[0],(float)msg[1],(float)msg[2]);
                    fflush(file);
                    }

                }
				printf("已跳出！\n");
            }
        }

        if(numBytesRcvd1 < 0) {
            perror("recv failed");
            break;
        }
        break;
                
    }

    if (file != NULL) {
        fclose(file); 
        printf("1.txt已关闭\n");// 关闭文件
    }

    close(conn_fd);
    return NULL;
}


void verify()
{
	int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(socket_fd < 0) {
        perror("socket creation failed");
        exit(-1);
    }

    struct sockaddr_in srvaddr;
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_port = htons(55555);
    srvaddr.sin_addr.s_addr = inet_addr("192.168.64.7");

    if(bind(socket_fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) < 0) {
        perror("bind failed");
        exit(-1);
    }

    if(listen(socket_fd, 4) < 0) {
        perror("listen failed");
        exit(-1);
    }

    printf("Waiting for client connection...\n");

    while(1) {
        int conn_fd = accept(socket_fd, NULL, NULL);
        if(conn_fd < 0) {
            perror("accept failed");
            continue;
        }

        printf("连接成功\n");

        pthread_t thread;
        pthread_create(&thread, NULL, handle_client, &conn_fd);
    }

	printf("登录成功！欢迎使用！\n");
    close(socket_fd);
} 


///////////////////////////////////////////////////////////////////-TCP 发送数据函数


void send_data(int socket_fd) {
    FILE* pf = fopen("1.txt", "r");
    long long  msg[3] = {0};
    long long da=0;
    float tm=0;
    float hu=0;
    if (pf != NULL) {
			msg[0]=0;
            msg[1]=0;
            msg[2]=0;
			send(socket_fd, msg, sizeof(msg), 0);
        while (fscanf(pf, "%lld %f %f", &da, &tm, &hu) != EOF) {
            // 在这里处理日期和时间
            msg[0]=da;
            msg[1]=tm;
            msg[2]=hu;
            if(send(socket_fd, msg, sizeof(msg), 0) < 0) {
                perror("send failed");
                exit(-2);
            }else
			{
				printf("消息已发送\n");
			}
        }
    } else {
        perror("open\n");
        exit(-1);
    }    
	fclose(pf);
}



///////////////////////////////////////////////////////////////////

void excute(int socket_fd)
{
	
	SLTNode* plist = NULL;

	Readfile(&plist);
	int flag = 1;
	while (flag)
	{
		menu();
		printf("请选择操作命令:");
		scanf("%d", &flag);
		switch (flag)
		{
		case 1://录入信息
		{
			input(&plist);
			Savefile(plist);
			send_data(socket_fd);
		}
		break;
		case 2://修改信息
		{
			printf("输入要修改的日期：");
			long long x = 0;
			scanf("%lld", &x);
			Change(plist, x);
			Savefile(plist);
			send_data(socket_fd);
		}
		break;
		case 3://显示信息
		{
			if (plist)
			{
				SLTPrint(plist);
				Savefile(plist);
				send_data(socket_fd);
			}
			else
			{
				printf("系统中无数据！\n");
			}

		}
		break;
		case 4://删除信息
		{
			printf("输入要删除的日期：");
			long long x = 0;
			scanf("%lld", &x);
			SLTNode* pos = SLTFind(plist, x);
			if (pos)
			{
				SLTPopBack(&plist, pos);
				Savefile(plist);
				send_data(socket_fd);
			}
			else
			{
				printf("无该日期数据！\n");
			}

		}
		break;
		case 5://删除所有数据
		{
			SLTDestroy(&plist);
			printf("已删除所有数据！\n");
			Savefile(plist);
			send_data(socket_fd);
		}
		break;
		case 6://退出系统
		{
			Savefile(plist);
			printf("退出系统成功！数据已保存至1.txt\n");
			flag = 0;
			send_data(socket_fd);
		}
		break;
		default:
		{
			printf("输入错误！请输入正确的指令！\n");
		}
		break;
		}
		if (flag != 3 && flag != 1 && flag != 0)
			system("cls");//清屏
	}

}


int main()
{
	//test();
	//excute();
	verify();
	//menu2();
	return 0;
}


